package com.gjp.shiroRealms;

import java.util.HashSet;
import java.util.Set;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import com.gjp.bean.Roles;
import com.gjp.bean.User;
import com.gjp.service.RolesService;
import com.gjp.service.UserService;

/**
 * 
 * @author gjp
 *
 */
public class SecondRealm extends AuthorizingRealm
{

	@Autowired
	UserService userService;
	@Autowired
	RolesService rolesService;

	/**
	 * 认证:当调用UsernamePasswordToken的login方法时,执行此方法
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken token) throws AuthenticationException
	{
		// 1.把AuthenticationToken转换成UsernamePasswordToken
		UsernamePasswordToken upToken = (UsernamePasswordToken) token;

		// 2.从UsernamePasswordToken中 获取username
		String username = upToken.getUsername();

		// 3.调用数据库方法，从数据库中查询username对应用户记录
		User user = new User();
		user.setUsername(username);
		user = userService.selectUserByName(user);

		// 4.若用户不存在则可以抛出AuthenticationException异常
		if (user.getUsername() == null && user.getUsername() == "")
		{
			throw new UnknownAccountException("用户不存在");
		}

		// 5.根据用户信息的情况，决定是否还需要抛出其他异常
		// if ("lock".equals(username))
		// {
		// throw new LockedAccountException("用户被锁定");
		// }

		// 6.根据用户情况，来构建AuthenticationInfo对象并返回,通常使用的是SimpleAuthenticationInfo
		// 1.principal:认证的实体信息，可以是username,也可以是bean对象
		// Object principal = username;

		// admin:123456---SHA1-1024次加密密码:ce2f6417c7e1d32c1d81a797ee0b499f87c5de06
		// user:123456---
		// SHA1-1024次加密密码:073d4c3ae812935f23cb3f2a71943f49e082a718
		// Object credentials = null;
		// if ("admin".equals(username))
		// {
		// credentials = "ce2f6417c7e1d32c1d81a797ee0b499f87c5de06";
		// } else if ("user".equals(username))
		// {
		// credentials = "073d4c3ae812935f23cb3f2a71943f49e082a718";
		// }

		// 3.realmName:当前realm对象的name,调用父类的getName()方法获取即可
		// String realmName = getName();

		// 4.credentialsSalt: 盐值.
		ByteSource credentialsSalt = ByteSource.Util.bytes(user.getUsername());

		// 创建返回值对象
		SimpleAuthenticationInfo info = null;
		info = new SimpleAuthenticationInfo(user.getUsername(),
				user.getPassword(), credentialsSalt, getName());
		return info;
	}

	/**
	 * 授权: 某一个用户访问需要权限的资源时，调用此方法
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(
			PrincipalCollection principals)
	{
		// 1、从PrincipalCollection中获取登录用户的信息
		Object principal = principals.getPrimaryPrincipal();
		// 2、从登录用户的信息，来获取当前用户的角色和权限(可能需要查询数据库)
		Set<String> roles = new HashSet<String>();
		// 创建用户
		User user = new User();
		user.setUsername((String) principal);
		// 查询当前用户详细信息
		user = userService.selectUserByName(user);
		// 将逗号分隔的角色id切分
		String[] rolesIdArr = user.getRolesid().split(",");
		for (int i = 0; i < rolesIdArr.length; i++)
		{
			Roles role = new Roles();
			role.setId(Integer.valueOf(rolesIdArr[i]));
			//查询对应的角色信息
			role = rolesService.selectRolesById(role);
			//将角色信息存入集合
			roles.add(role.getRolename());
		}

		// 3、创建 SimpleAuthorizationInfo,并设置其属性roles属性.
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		info.setRoles(roles);
		// 4、返回对象
		return info;
	}

	/**
	 * SHA1加密测试方法 
	 * @param args
	 */
	
	public static void main(String[] args)
	{
		String algorithmName = "SHA1"; // 加密次数
		Object source = "123456"; // 原密码
		Object salt = ByteSource.Util.bytes("admin"); // 盐
		System.out.println(salt);
		int iterations = 1024; // 加密次数
		SimpleHash simpleHash = new SimpleHash(algorithmName, source, salt,
				iterations);
		System.out.println(simpleHash); // 加密结果
	}

}
